package self.hoy.demo.grainmall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import self.hoy.demo.common.utils.PageUtils;
import self.hoy.demo.common.utils.Query;

import self.hoy.demo.common.constant.ProductConstant;
import self.hoy.demo.grainmall.product.entity.AttrAttrgroupRelation;
import self.hoy.demo.grainmall.product.entity.AttrGroup;
import self.hoy.demo.grainmall.product.entity.Category;
import self.hoy.demo.grainmall.product.mapper.AttrAttrgroupRelationMapper;
import self.hoy.demo.grainmall.product.mapper.AttrGroupMapper;
import self.hoy.demo.grainmall.product.mapper.AttrMapper;
import self.hoy.demo.grainmall.product.entity.Attr;
import self.hoy.demo.grainmall.product.service.AttrService;
import self.hoy.demo.grainmall.product.service.CategoryService;
import self.hoy.demo.grainmall.product.vo.AttrRelationVo;
import self.hoy.demo.grainmall.product.vo.AttrRespVo;
import self.hoy.demo.grainmall.product.vo.AttrVo;

import javax.annotation.Resource;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrMapper, Attr> implements AttrService {

    @Resource
    private AttrAttrgroupRelationMapper relationMapper;

    @Resource
    private CategoryService categoryService;

    @Resource
    private AttrGroupMapper attrGroupMapper;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<Attr> page = this.page(
                new Query<Attr>().getPage(params),
                new QueryWrapper<Attr>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void saveAttr(AttrVo attr) {
        Attr a = new Attr();
        BeanUtils.copyProperties(attr, a);
        this.save(a);
        if (attr.getAttrGroupId() != null && attr.getAttrType() == ProductConstant.ATTR_TYPE.BASE.getType()) {
            AttrAttrgroupRelation aar = new AttrAttrgroupRelation();
            aar.setAttrGroupId(attr.getAttrGroupId());
            aar.setAttrId(a.getAttrId());
            relationMapper.insert(aar);
        }
    }

    @Override
    public PageUtils queryBaseAttr(Map<String, Object> params, Long catelogId, String attrType) {
        Integer type = "base".equalsIgnoreCase(attrType) ?
                ProductConstant.ATTR_TYPE.BASE.getType(): ProductConstant.ATTR_TYPE.SALE.getType();
        QueryWrapper<Attr> wrapper = new QueryWrapper<>();
        wrapper.eq("attr_type", type);
        if (catelogId != null && catelogId.longValue() != 0L) {
            wrapper.eq("catelog_id", catelogId);
        }
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.eq("attr_id", key).or().like("attr_name", key);
        }

        IPage<Attr> page = this.page(
                new Query<Attr>().getPage(params),
                wrapper
        );

        List<Attr> records = page.getRecords();
        PageUtils pages = new PageUtils(page);
        List<AttrRespVo> respVoList = records.stream().map((attr)->{
            AttrRespVo r = new AttrRespVo();
            BeanUtils.copyProperties(attr, r);
            if (type.intValue() == 1) {
                AttrAttrgroupRelation relation = relationMapper.selectOne(
                        new QueryWrapper<AttrAttrgroupRelation>().eq("attr_id", attr.getAttrId()));
                if (relation != null) {
                    AttrGroup group = attrGroupMapper.selectById(relation.getAttrGroupId());
                    r.setGroupName(group == null ? "" : group.getAttrGroupName());
                }
            }
            Category category = categoryService.getById(attr.getCatelogId());
            if (category != null) {
                r.setCatelogName(category.getName());
            }
            return r;
        }).collect(Collectors.toList());
        pages.setList(respVoList);
        return pages;
    }

    @Override
    public AttrRespVo getAttrInfo(Long attrId) {
        Attr entity = this.getById(attrId);
        AttrRespVo vo = new AttrRespVo();
        BeanUtils.copyProperties(entity, vo);

        if (ProductConstant.ATTR_TYPE.BASE.getType() == entity.getAttrType()) {
            AttrAttrgroupRelation relation = relationMapper.selectOne(
                    new QueryWrapper<AttrAttrgroupRelation>().eq("attr_id", attrId)
            );
            if (relation != null) {
                vo.setAttrGroupId(relation.getAttrGroupId());
                AttrGroup attrGroup = attrGroupMapper.selectById(relation.getAttrGroupId());
                vo.setGroupName(attrGroup == null ? "" : attrGroup.getAttrGroupName());
            }
        }
        Category category = categoryService.getById(entity.getCatelogId());
        if (category != null) {
            vo.setCatelogName(category.getName());
            Long[] paths = categoryService.findPath(entity.getCatelogId());
            vo.setCatelogPath(paths);
        }
        return vo;
    }

    @Override
    @Transactional
    public void updateAttr(AttrVo attr) {
        Attr entity = new Attr();
        BeanUtils.copyProperties(attr, entity);
        baseMapper.updateById(entity);

        if (attr.getAttrGroupId() != null && ProductConstant.ATTR_TYPE.BASE.getType() == entity.getAttrType()) {
            AttrAttrgroupRelation param = new AttrAttrgroupRelation();
            param.setAttrGroupId(attr.getAttrGroupId());
            param.setAttrId(entity.getAttrId());

            Integer counts = relationMapper.selectCount(
                    new QueryWrapper<AttrAttrgroupRelation>().eq("attr_id", attr.getAttrId()));
            if (counts > 0) {
                //UPDATE   SET WHERE
                relationMapper.update(param,
                        new UpdateWrapper<AttrAttrgroupRelation>().eq("attr_id", attr.getAttrId()));
            } else {
                relationMapper.insert(param);
            }
        }
    }

    @Override
    public List<Attr> getRelationAttr(Long attrgroupId) {
        QueryWrapper<AttrAttrgroupRelation> wrapper = new QueryWrapper<AttrAttrgroupRelation>();
        wrapper.eq("attr_group_id", attrgroupId);
        List<AttrAttrgroupRelation> relations = relationMapper.selectList(wrapper);
        List<Long> attrIds = relations.stream().map((relation)->{
            return relation.getAttrId();
        }).collect(Collectors.toList());

        Collection<Attr> attrs = attrIds == null || attrIds.isEmpty() ?
                new LinkedList<>() : this.listByIds(attrIds);
//        return new LinkedList<>(attrs);
        return (List<Attr>) attrs;
    }

    @Override
    public void deleteRelation(AttrRelationVo[] vos) {
        List<AttrAttrgroupRelation> list = Arrays.asList(vos).stream().map((v) -> {
            AttrAttrgroupRelation r = new AttrAttrgroupRelation();
            BeanUtils.copyProperties(v, r);
            return r;
        }).collect(Collectors.toList());
        relationMapper.deleteBatchRelations(list);
    }

    @Override
    public PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId) {
        //1、当前分类只能关联自己所属的分类里面的所有属性
        AttrGroup attrGroup = attrGroupMapper.selectById(attrgroupId);
        Long catelogId = attrGroup.getCatelogId();

        //2、当前分组只能关联别的组没有引用的属性
        //2.1、当前分类下的其它分组
        List<AttrGroup> groups = attrGroupMapper.selectList(
                new QueryWrapper<AttrGroup>()
                        .eq("catelog_id", catelogId)
//                        .ne("attr_group_id", attrgroupId)// 修复误把自己排除的bug
        );
        List<Long> groupIds = groups.stream().map((g) -> {
            return g.getAttrGroupId();
        }).collect(Collectors.toList());

        //2.2、这些分组关联的属性
        List<AttrAttrgroupRelation> relations = groupIds == null || groupIds.isEmpty() ?
                new LinkedList<>() :relationMapper.selectList(
                        new QueryWrapper<AttrAttrgroupRelation>()
                                .in("attr_group_id", groupIds)
        );

        List<Long> attrIds = relations == null || relations.isEmpty() ?
                null :
                relations.stream().map((r)->{
                    return r.getAttrId();
                }).collect(Collectors.toList());

        //2.3、从当前分类的所有属性中移除这些属性
        QueryWrapper<Attr> wrapper = new QueryWrapper<Attr>()
                .eq("catelog_id", catelogId)
                .eq("attr_type", ProductConstant.ATTR_TYPE.BASE.getType());
        if(attrIds != null && attrIds.size() > 0) {
            wrapper.notIn("attr_id", attrIds);
        }
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.and((w)->{
                w.eq("attr_id", key)
                        .or()
                        .like("attr_name", key);
            });
        }
        IPage<Attr> page = this.page(new Query<Attr>().getPage(params), wrapper);
        return new PageUtils(page);
    }

    @Override
    public List<Long> selectSearchAttrIds(List<Long> attrIds) {
        List<Attr> attrs = this.baseMapper.selectList(
                new QueryWrapper<Attr>().eq("search_type", 1).in("attr_id", attrIds)
        );
        return attrs.stream().map(attr -> attr.getAttrId()).collect(Collectors.toList());
    }

}